package user

import (
	"time"

	"gitee.com/xiaoyutab/gatway/config"
	"gitee.com/xiaoyutab/gatway/model"
	"gitee.com/xiaoyutab/xgotool/optional/xcache"
	"gitee.com/xiaoyutab/xgotool/xerror"
	"gitee.com/xiaoyutab/xgotool/xgodb"
	"gitee.com/xiaoyutab/xgotool/xstring"
)

// 登录用户信息
//
//	username	登录账户名
//	password	登录密码
//	login_ip	登录客户端IP
func Login(username, password, login_ip string) (string, *model.User, error) {
	// 查询用户详情
	user_info, err := GetInfoByUserName(username)
	if err != nil {
		return "", nil, err
	}
	if user_info.Id == 0 {
		return "", nil, xerror.New("用户名/密码输入不匹配")
	}
	if user_info.Status == 1 {
		return "", nil, xerror.New("用户禁止登录")
	}
	if user_info.IsLock == 1 {
		return "", nil, xerror.NewFmt("用户密码已被锁定，请 %ds 以后再试", xgodb.GetInt("USER_LOCK_TIME"))
	}
	pass, err := Passwd(password, user_info.RandCode)
	if err != nil {
		return "", nil, err
	}
	// 密码效验
	if user_info.Password != pass {
		// 记录密码输入错误日志
		Log(user_info.Id, 3, login_ip)
		// 密码输入错误次数效验
		if err_pass_num(user_info.Id, user_info.LoginTime) >= xgodb.GetInt("USER_ERROR_LOCK") {
			// 密码输入错误次数达到锁定次数，进行状态锁定
			Log(user_info.Id, 4, login_ip) // 锁定的记录仅为记录，主要锁定为用户的状态信息中
			user_info.LockTime = time.Now().Format(time.DateTime)
			user_info.IsLock = 1
			err := config.DB.Table(user_info.TableName()).Select("is_lock", "lock_time").Save(&user_info).Error
			if err != nil {
				return "", nil, xerror.To(err)
			}
			// 缓存更新
			xcache.SetStruct(xcache.Key("service.user.get.info.by.id", user_info.Id), user_info)             // 用户ID缓存
			xcache.SetStruct(xcache.Key("service.user.get.info.by.username", user_info.Username), user_info) // 用户Username缓存
		}
		return "", nil, xerror.New("用户名/密码输入不匹配")
	}
	// 记录登录日志
	Log(user_info.Id, 0, login_ip)
	// 生成token
	token := xstring.UUID()
	// token存储到缓存中
	xcache.SetStruct(xcache.Key("service.user.token", token), user_info)
	return token, user_info, nil
}

// 获取用户距离上次登录时的密码输入错误次数
//
//	uid	用户id
//	t	上次登录时间
func err_pass_num(uid uint, t string) int64 {
	var count int64
	log := model.UserLoginlog{}
	err := config.DB.Table(log.TableName()).
		Where("uid", uid).
		Where("type", 3).
		Where("created_at > ?", t).
		Count(&count).
		Error
	if err != nil {
		return 0
	}
	return count
}
